import numpy as np
from videoCapture import videoCapture
from preProcess import preProcess
from FeatureCal import FeatureCal
from dataFind import dataFind
from PyQt5.QtCore import Qt, pyqtSignal
from untitled import Ui_MainWindow
from PyQt5.QtWidgets import QLabel, QFileDialog, QApplication, QStyleFactory, QMainWindow, QMessageBox
from PyQt5.QtGui import QImage, QPixmap, QPen, QPainter
import cv2
import matplotlib.pyplot as plt
import os
from heightCal import heightCal
from wFeatureCal import wFeatureCal
from cutSludge import cutSludge
from wuCal import wuCal
import sys


# 这是一个示例 Python 脚本。

# 按 Shift+F10 执行或将其替换为您的代码。
# 按 双击 Shift 在所有地方搜索类、文件、工具窗口、操作和设置。


# 截取图片类
class ImageLabel(QLabel):
    '''获取用户裁剪坐标点，画线
        Attributes:
            points:用户点击的裁剪点
        '''

    def __init__(self, parent=None):
        super(ImageLabel, self).__init__(parent)
        self.points = []

    # normal function
    def show_image(self, image):
        # 参数image为np.array类型
        rgb_image = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2RGB)
        frame_width = image.shape[1]
        frame_height = image.shape[0]
        print("yuantu", frame_height, frame_width)
        print("rgbtu", rgb_image.shape[0], rgb_image.shape[1])

        # ratio=frame_width/frame_height
        # if (frame_width/frame_height)<(1100/600):
        #     frame_height=600
        #     frame_width=int(600*ratio)
        # else:
        #     frame_width=1100
        #     frame_height=int(1100/ratio)
        # rgb_image = cv2.resize(rgb_image, (frame_width, frame_height))
        label_image = QImage(rgb_image.data, rgb_image.shape[1], rgb_image.shape[0], rgb_image.shape[1] * 3,
                             QImage.Format_RGB888)
        print("label im", label_image)
        self.setPixmap(QPixmap(label_image))

    def reselect(self):
        self.points.clear()
        self.update()

    def get_points(self):
        return self.points

    # slot function
    # 根据点过的点来画图
    def paintEvent(self, event):
        QLabel.paintEvent(self, event)
        painter = QPainter()
        painter.begin(self)

        pen = QPen(Qt.red, 4, Qt.DashDotLine)  # 虚线画笔
        painter.setPen(pen)

        for k in range(len(self.points)):
            if k == 0:
                painter.drawLine(self.points[k][0], self.points[k][1], self.points[0][0], self.points[0][1])
            else:
                painter.drawLine(self.points[0][0], self.points[0][1], self.points[0][0], self.points[1][1])
                painter.drawLine(self.points[0][0], self.points[0][1], self.points[1][0], self.points[0][1])
                painter.drawLine(self.points[1][0], self.points[0][1], self.points[1][0], self.points[1][1])
                painter.drawLine(self.points[0][0], self.points[1][1], self.points[1][0], self.points[1][1])
        painter.end()

    # 开启标记功能时，获取点击坐标
    def mouseReleaseEvent(self, event):
        if len(self.points) < 2:
            global_point = event.globalPos()
            local_point = self.mapFromGlobal(global_point)

            point_x = local_point.x()
            point_y = local_point.y()
            self.points.append([point_x, point_y])

            self.update()  # 获取鼠标点击的点之后，通知画线


# 窗口类
class MainApp(QMainWindow, Ui_MainWindow):
    ok_signal = pyqtSignal()

    # 定义构造方法
    def __init__(self):
        QMainWindow.__init__(self)
        self.setupUi(self)
        self.handle_buttons()
        self.handle_ui_change()
        self.open_start_tab()

    # UI变化处理
    def handle_ui_change(self):
        self.tabWidget.tabBar().setVisible(False)
        self.groupBox.setStyleSheet(("border:none"))
        self.groupBox_2.setStyleSheet(("border:none"))
        self.groupBox_3.setStyleSheet(("border:none"))
        self.groupBox_4.setStyleSheet(("border:none"))
        self.groupBox_5.setStyleSheet(("border:none"))

    # 所有Button的消息与槽的通信
    def handle_buttons(self):

        # ----------------------- tab页面切换按钮 -----------------------
        self.action_open.triggered.connect(self.vLuJing)
        self.action_chouYang.triggered.connect(self.open_chouYang_tab)  # 视频抽样按钮
        self.action_pre.triggered.connect(self.open_yuChuLi_tab)  # 预处理按钮
        self.action_cal.triggered.connect(self.open_teZheng_tab)  # 图像特征计算按钮
        self.action_find.triggered.connect(self.open_jieGuo_tab)  # 特征结果查询按钮
        self.action_cal_w.triggered.connect(self.open_teZheng_tab_w)
        self.action_find_w.triggered.connect(self.open_jieGuo_tab_w)
        # self.action_wu.triggered.connect(self.open_wushui_tab)
        # ----------------------- 视频截取抽样部分 页面按钮功能通信 -----------------------
        # self.ok_button.clicked.connect(self.on_ok_button)
        self.reselect_button.clicked.connect(self.on_reselect_button)
        self.chouYang_path_save_button.clicked.connect(self.caiBaoCun)  # 抽样图像保存路径选择
        self.push1_Button.clicked.connect(self.videoCap)

        # ----------------------- 图片预处理部分 页面按钮功能通信 -----------------------
        # 图片预处理路径选择
        self.preProce_path_button.clicked.connect(self.preProce_path_button_func)
        # 预处理结果保存路径选择
        self.preProce_path_save_button.clicked.connect(self.preProce_path_save_button_func)
        # 点击按钮开始预处理
        self.preProce_submit_button.clicked.connect(self.preProce_submit_func)

        # ----------------------- 特征计算保存部分 页面按钮功能通信 -----------------------
        # 图片预处理路径选择
        self.feature_path_button.clicked.connect(self.feature_path_button_func)
        # 预处理结果保存路径选择
        self.feature_path_save_button.clicked.connect(self.feature_path_save_button_func)
        # 特征计算开始计算
        self.feature_submit_button.clicked.connect(self.feature_submit_func)

        # ----------------------- 结果查询界面部分 页面按钮功能通信 -----------------------
        # 保存数据内容路径选择
        self.data_path_button.clicked.connect(self.data_path_button_func)
        # 点击提交查询按钮功能绑定
        self.data_submit_button.clicked.connect(self.data_submit_button_func)
        # self.chouYang_Button.clicked.connect(self.open_chouYang_tab)   #视频抽样按钮
        # self.yuChuLi_Button.clicked.connect(self.open_yuChuLi_tab)     #预处理按钮
        # self.teZheng_Button.clicked.connect(self.open_teZheng_tab)     #图像特征计算按钮
        # self.jieGuo_Button.clicked.connect(self.open_jieGuo_tab)       #特征结果查询按钮
        #
        # self.vLuJing_Button.clicked.connect(self.vLuJing)              #视频路径选择按钮
        self.data_path_button_2.clicked.connect(self.data_path_button_2_func)
        self.data_path_button_3.clicked.connect(self.data_path_button_3_func)
        self.data_submit_button_2.clicked.connect(self.data_submit_button_2_func)
        self.data_submit_button_3.clicked.connect(self.data_submit_button_3_func)
        self.data_submit_button_4.clicked.connect(self.data_submit_button_4_func)
        self.feature_path_save_button_2.clicked.connect(self.feature_path_save_button_2_func)
        self.feature_submit_button_2.clicked.connect(self.feature_submit_button_2_func)

    def feature_submit_button_2_func(self):
        wuCal(self.wuProcess_path.text(), self.feature_save_path_2.text())
        msg_box = QMessageBox(QMessageBox.Information, '成功', '已经计算并保存!')
        msg_box.exec_()
        self.open_jieGuo_tab_w()

    def feature_path_save_button_2_func(self):
        self.feature_save_path_2.setText(QFileDialog.getExistingDirectory())

    def data_path_button_2_func(self):
        self.wuProcess_path.setText(QFileDialog.getExistingDirectory())

    def data_path_button_3_func(self):
        self.data_path_2.setText(QFileDialog.getOpenFileName()[0])

    def data_submit_button_2_func(self):

        heightCal(self.data_path_2.text(), int(self.gray_type_4.currentIndex()))

    def data_submit_button_3_func(self):
        cutSludge(self.data_path_2.text(), int(self.gray_type_7.currentIndex()))

    def data_submit_button_4_func(self):
        wFeatureCal(self.data_path_2.text(), int(self.gray_type_6.currentIndex()))

    # 选项卡联动
    def open_start_tab(self):
        self.tabWidget.setCurrentIndex(0)

    def open_chouYang_tab(self):
        self.tabWidget.setCurrentIndex(1)
        self.chouYang_save_lineEdit.setText("D:/python/picture_or")

    def open_yuChuLi_tab(self):
        self.tabWidget.setCurrentIndex(2)
        self.preProce_path.setText(self.chouYang_save_lineEdit.text())
        self.preProce_path_save.setText("D:/python/picture_gr")
        self.gauss_para.setText("30")
        self.median_para.setText("3")

    def open_teZheng_tab(self):
        self.tabWidget.setCurrentIndex(3)
        self.feature_path.setText(self.preProce_path_save.text())
        self.feature_save_path.setText("D:/python/excel")

    def open_teZheng_tab_w(self):
        self.tabWidget.setCurrentIndex(5)
        self.wuProcess_path.setText(self.chouYang_save_lineEdit.text())
        self.feature_save_path_2.setText("D:/python/excel")

    def open_jieGuo_tab(self):
        self.tabWidget.setCurrentIndex(4)
        self.data_path.setText(self.feature_save_path.text() + "/excel.xlsx")

    def open_jieGuo_tab_w(self):
        self.tabWidget.setCurrentIndex(6)
        self.data_path.setText(self.feature_save_path_2.text() + "/excel.xlsx")

    # ----------------------- 视频截取抽样部分 页面按钮功能通信  start -----------------------

    # 按钮功能
    # def on_ok_button(self):         #截取位置确定按钮
    #     if len(self.image_label.get_points()) != 2:  # 判断是否选取完
    #         reply = QMessageBox.warning(self,
    #                                     "提示",
    #                                     "请选取两个点",
    #                                     QMessageBox.Ok)
    #         return
    #
    #     reply = QMessageBox.warning(self,
    #                                 "提示",
    #                                 "你确定截取好了吗",
    #                                 QMessageBox.Yes | QMessageBox.No)
    #     if reply == QMessageBox.No:
    #         self.on_reselect_button()
    #     else:
    #         self.ok_signal.emit()

    def on_reselect_button(self):  # 截取位置取消按钮
        self.image_label.reselect()

    def caiBaoCun(self):  # 抽样图像保存路径选择按钮
        self.chouYang_save_lineEdit.setText(QFileDialog.getExistingDirectory())

    # 预览图片截取
    def preview(self):
        # 视频路径
        vc = cv2.VideoCapture(self.luJing_lineEdit.text())
        k = 0
        # 抽取第50帧进行预览
        while k < 50:
            vc.read()
            k = k + 1
        rval, frame = vc.read()
        return frame

    def show_im(self):
        self.image = self.preview()
        print(self.image.shape[0], self.image.shape[1])
        # 设置宽高比
        frame_width = self.image.shape[1]
        frame_height = self.image.shape[0]
        w_h_ratio = frame_width / frame_height
        # w_h_ratio = self.label.width() * 1.0 / self.label.height()
        print(self.label.width())
        print(self.label.height())
        print("w_h_ration", w_h_ratio)
        print((int)(self.image.shape[0] * w_h_ratio))
        if (frame_width / frame_height) < (1100 / 600):
            frame_height = 600
            frame_width = int(600 * w_h_ratio)
        else:
            frame_width = 1100
            frame_height = int(1100 / w_h_ratio)
        print("h,w", frame_height, frame_width)
        self.image = cv2.resize(self.image, (frame_width, frame_height))

        self.image_label = ImageLabel(self.label)

        self.image_label.show_image(self.image)

    def get_image(self):
        return self.image

        # 根据左上、左下，右下，右上的顺序排序

    # 排列截取点
    def order_points(self, points):
        # 求中心点的坐标
        center = [0, 0]
        for point in points:
            center[0] += point[0]
            center[1] += point[1]
        center[0] = center[0] / 2
        center[1] = center[1] / 2
        print(center)
        # 根据中心点x坐标，大于为左，小于为右
        left = []
        right = []
        for point in points:
            if point[0] > center[0]:
                right.append(point)
            else:
                left.append(point)
        return [left, right]

    # 将截取点映射到原图像
    def mapfromLoal(self, points):
        # 从局部点投影到原图，并且将4个点的顺序，按照左上、左下，右下，右上的顺序排序
        points_origanal = []
        print("in map shape:", self.image.shape)
        print("before largen", points)

        y_ratio = np.float32(self.preview().shape[0] / self.image_label.height())
        x_ratio = np.float32(self.preview().shape[1] / self.image_label.width())
        for point in points:
            points_origanal.append([point[0] * x_ratio, point[1] * y_ratio])

        order_points = self.order_points(points_origanal)
        print("order", order_points)
        return order_points
        # return points_origanal

    # 提示信息
    def show1(self):
        vc = cv2.VideoCapture(self.luJing_lineEdit.text())
        fps = vc.get(cv2.CAP_PROP_FPS)
        fps = round(fps, 2)
        frame_all = vc.get(cv2.CAP_PROP_FRAME_COUNT)
        time_all = frame_all / fps
        time_all = round(time_all, 2)
        frame_interval = int(int(self.jianGe_lineEdit.text()) * fps)
        count_p = int(frame_all / frame_interval)
        reply = QMessageBox.about(self, "视频相关信息", "视频FPS: {}每秒<br /> 视频总帧数: {}< br />"
                                                  " 视频时长：{}秒< br />共需保存： {}张图片< br />".format(fps, frame_all, time_all,
                                                                                              count_p))
        print(reply)

    def show2(self):
        vc = cv2.VideoCapture(self.luJing_lineEdit.text())
        fps = vc.get(cv2.CAP_PROP_FPS)
        fps = round(fps, 2)
        frame_all = vc.get(cv2.CAP_PROP_FRAME_COUNT)
        frame_interval = int(int(self.jianGe_lineEdit.text()) * fps)
        count_p = int(frame_all / frame_interval)
        reply = QMessageBox.about(self, "", "成功保存{}张图片".format(count_p))
        print(reply)

        # normal function

    def show3(self):
        vc = cv2.VideoCapture(self.luJing_lineEdit.text())
        fps = vc.get(cv2.CAP_PROP_FPS)
        fps = round(fps, 2)
        frame_all = vc.get(cv2.CAP_PROP_FRAME_COUNT)
        frame_interval = int(self.jianGe_lineEdit.text()) * fps
        count_p = int(frame_all / frame_interval)
        ratio = int(count_p / 15)
        sa = self.chouYang_save_lineEdit.text()
        # if (self.baoCun_lineEdit.text() != ""):
        #     sa = self.baoCun_lineEdit.text()
        N = 5
        M = 3
        plt.figure(figsize=(60, 30))
        plt.figure(1)
        # 形成NxM大小的画布
        for i in range(15):
            path = sa + '/picture-' + str(i * ratio) + '.jpg'
            img = plt.imread(path)
            plt.subplot(N, M, int(i) + 1)  # 表示第i张图片，下标只能从1开始，不能从0，
            plt.title(str(i * ratio + 1), fontsize=15, pad=2)
            plt.imshow(img)
            # 下面两行是消除每张图片自己单独的横纵坐标，不然每张图片会有单独的横纵坐标，影响美观
            plt.xticks([])
            plt.yticks([])
        plt.show()

    # 文件路径选择
    def vLuJing(self):
        self.luJing_lineEdit.setText(QFileDialog.getOpenFileName()[0])
        self.show_im()
        self.open_chouYang_tab()

    # 视频抽样
    def videoCap(self):
        self.show1()
        # self.setCursor(Qt.WaitCursor)
        points = self.image_label.get_points()
        # 单适应变换
        print("points", points)
        points_origanal = self.mapfromLoal(points)

        print("src_point", points_origanal)
        print(points_origanal[0][0][1])
        h1 = int(points_origanal[0][0][1])
        h2 = int(points_origanal[1][0][1])
        w1 = int(points_origanal[0][0][0])
        w2 = int(points_origanal[1][0][0])
        path = self.chouYang_save_lineEdit.text()

        videoCapture(self.luJing_lineEdit.text(), self.jianGe_lineEdit.text(), h1, h2, w1, w2,
                     self.chouYang_save_lineEdit.text())
        # tkinter.Button(self, text='cursor_style', cursor='arrow').pack()
        # self.setCursor(Qt.SizeAllCursor)
        self.show2()
        self.show3()
        if int(self.gray_type_3.currentIndex()) == 0:
            self.open_yuChuLi_tab()
        else:
            self.open_teZheng_tab_w()

    # ----------------------- 视频截取抽样部分 页面按钮功能通信  end -----------------------

    # ----------------------- 图像预处理部分 页面按钮功能通信  start -----------------------

    # 截取图片保存的路径选择
    def preProce_path_button_func(self):
        self.preProce_path.setText(QFileDialog.getExistingDirectory())

    # 保存路径选择
    def preProce_path_save_button_func(self):
        self.preProce_path_save.setText(QFileDialog.getExistingDirectory())

    # 点击提交按钮的功能
    def preProce_submit_func(self):
        # self.preProce_path.setText(QFileDialog.getExistingDirectory())
        # if self.preProce_path.text() == '' or self.pic_start.text() == '' or self.pic_end.text() == '' or self.preProce_gap.text() == '' or self.preProce_path_save.text() == '':
        #     msg_box = QMessageBox(QMessageBox.Warning, '提示', '请确保全部信息都完整输入!')
        #     msg_box.exec_()
        # else:
        path = self.preProce_path.text()
        count = 0
        for file in os.listdir(path):  # file 表示的是文件名
            count = count + 1
        print(count)
        preProcess(self.preProce_path.text(), 1, 0,
                   count - 1, int(self.gray_type.currentIndex()),
                   self.preProce_path_save.text(), int(self.gauss_para.text()),
                   int(self.median_para.text()), )

        msg_box = QMessageBox(QMessageBox.Information, '成功', '已完成预处理操作!')
        msg_box.exec_()
        self.show_pre()
        self.open_teZheng_tab()
        # print('path', self.preProce_path.text())
        # print('gap', self.preProce_gap.text())
        # print('pic_start', self.pic_start.text())
        # print('pic_end', self.pic_end.text())
        # print('path_save', self.preProce_path_save.text())
        # # 获取下拉列表框中选择的内容
        # print('gray_type', self.gray_type.currentText())
        # # 获取下拉列表框中选择的内容的索引下标
        # print('gray_type_index', self.gray_type.currentIndex())

    def show_pre(self):
        path = self.preProce_path.text()
        count = 0
        for file in os.listdir(path):  # file 表示的是文件名
            count = count + 1
        ratio = int(count / 5)
        print(ratio)
        N = 5
        M = 2
        # 形成NxM大小的画布
        plt.figure(figsize=(32, 16))
        plt.figure(1)
        for i in range(5):
            path = self.preProce_path.text() + '/picture-' + str(i * ratio) + '.jpg'
            path1 = self.preProce_path_save.text() + '/gray-' + str(i * ratio) + '.png'

            img = plt.imread(path)
            img1 = plt.imread(path1)
            plt.subplot(N, M, int(i * 2) + 1)  # 表示第i张图片，下标只能从1开始，不能从0，
            if i == 0:
                plt.title('Original Image', fontsize=25, pad=15)
            plt.imshow(img, cmap="gray")
            # 下面两行是消除每张图片自己单独的横纵坐标，不然每张图片会有单独的横纵坐标，影响美观
            plt.xticks([])
            plt.yticks([])

            plt.subplot(N, M, int(i * 2) + 2)  # 表示第i张图片，下标只能从1开始，不能从0，
            if i == 0:
                plt.title('Processed Image', fontsize=25, pad=15)
            plt.imshow(img1, cmap="gray")
            # 下面两行是消除每张图片自己单独的横纵坐标，不然每张图片会有单独的横纵坐标，影响美观
            plt.xticks([])
            plt.yticks([])
            print(i)
        plt.show()

    # ----------------------- 图像预处理部分 页面按钮功能通信  end -----------------------
    # ----------------------- 特征计算部分 页面按钮功能通信  start -----------------------
    # def FeatureCal(self, path, gap, pic_start, pic_end, gauss_para, median_para):
    #     # def FeatureCal(self, path, gap, pic_start, pic_end, gauss_para, median_para):
    #
    #     print(path)
    #     print(gap)
    #     print(pic_start)
    #     print(pic_end)
    #     print(gauss_para)
    #     print(median_para)

    def feature_path_button_func(self):
        self.feature_path.setText(QFileDialog.getExistingDirectory())

    def feature_path_save_button_func(self):
        self.feature_save_path.setText(QFileDialog.getExistingDirectory())

    def feature_submit_func(self):
        # print('图片路径?', self.feature_path.text())
        # print('图片间隔?', int(self.feature_gap.text()))
        # print('图片起始张数?', int(self.feature_pic_start.text()))
        # print('图片结束张数?', int(self.feature_pic_end.text()))
        # print('高斯模糊系数?', int(self.gauss_para.text()))
        # print('中值滤波系数?', int(self.median_para.text()))
        # # feature_number.isChecked() 检查复选框是否被选中 选中是True 没选中是False
        # print('絮体个数选中?', self.feature_number.isChecked())
        # print('絮体面积选中?', self.feature_area.isChecked())
        # print('等效直径选中?', self.ad.isChecked())
        # print('角二阶矩选中?', self.gray_asm.isChecked())
        # print('能量选中?', self.gray_energy.isChecked())
        # print('对比度选中?', self.feature_contrast.isChecked())
        # print('逆差矩选中?', self.feature_homo.isChecked())
        # print('相关系数选中?', self.feature_conrela.isChecked())
        # print('分形维数选中?', self.fractal_dimension.isChecked())
        # print('结果保存路径?', self.feature_save_path.text())
        path = self.feature_path.text()
        count = 0
        for file in os.listdir(path):  # file 表示的是文件名
            count = count + 1
        count = count - 1
        res = FeatureCal(self.feature_path.text(), 1,
                         0,
                         count, self.feature_save_path.text())
        msg_box = QMessageBox(QMessageBox.Information, '成功', '已经计算并保存!')
        msg_box.exec_()
        self.open_jieGuo_tab()
        # res.to_excel('./' + 'excel.xlsx')
        # print(res)

    # ----------------------- 特征计算部分 页面按钮功能通信  end -----------------------

    # ----------------------- 结果查询页面部分 页面按钮功能通信  start ---------------------

    def data_path_button_func(self):
        self.data_path.setText(QFileDialog.getOpenFileName()[0])

    # def ReadData(self,path):

    def data_submit_button_func(self):
        dataFind(self.data_path.text(), int(self.gray_type_2.currentIndex()))
    # ----------------------- 结果查询页面部分 页面按钮功能通信  end -----------------------


# 按间距中的绿色按钮以运行脚本。
def main():
    app = QApplication([])
    app.setStyle(QStyleFactory.create("Windows"))
    window = MainApp()
    window.showMaximized()
    app.exec_()


if __name__ == '__main__':
    main()
# 访问 https://www.jetbrains.com/help/pycharm/ 获取 PyCharm 帮助
